package org.example.myleet.rosalind.corr;

import org.example.myleet.rosalind.utils.DnaReverseComplementor;
import org.example.myleet.rosalind.utils.FastaReader;
import org.example.myleet.rosalind.utils.FastaSequence;

import java.util.*;
import java.util.stream.Collectors;

public class Solution {
    public static void main(String[] args) {
        Solution solution = new Solution();
        String path = solution.getClass().getResource("").getPath() + "example.txt";
        solution.correctErrorReads(FastaReader.parseFastaFromFile(path));
    }

    public void correctErrorReads(List<FastaSequence> sequences) {
        //保存相同序列的Fasta Entry
        Map<String, List<FastaSequence>> readGroup = sequences.stream().collect(Collectors.groupingBy(FastaSequence::getSequence));
        Set<String> unconfirmedReads = new HashSet<>(sequences.size() * 2);
        Set<String> correctReads = new HashSet<>(sequences.size() * 2);
        //find all correct reads and unconfirmed reads
        for (FastaSequence sequence : sequences) {
            //来自sequences的read
            String seq = sequence.getSequence();
            if (correctReads.contains(seq)) {
                continue;
            }
            //来自sequences的反向互补的read
            String reverseComplement = DnaReverseComplementor.reverseComplete(seq);
            if (correctReads.contains(reverseComplement)) {
                continue;
            }
            List<FastaSequence> sameSequences = readGroup.getOrDefault(sequence.getSequence(), Collections.emptyList());
            List<FastaSequence> revcSequences = readGroup.getOrDefault(reverseComplement, Collections.emptyList());
            if (sameSequences.size() + revcSequences.size() > 1) {
                //存在不同的read可以印证序列正确，则加入到correctReads
                correctReads.add(seq);
                correctReads.add(reverseComplement);
                readGroup.remove(seq);
                readGroup.remove(reverseComplement);
            } else {
                //序列是未被印证的
                unconfirmedReads.add(seq);
            }
        }
        //correct the unconfirmed reads
        for (String unconfirmed : unconfirmedReads) {
            for (String correct : correctReads) {
                if (hammingDistance(correct, unconfirmed) == 1) {
                    //汉明距离为1的情况可以做序列纠正
                    System.out.println(unconfirmed + "->" + correct);
                }
            }
        }
    }

    private int hammingDistance(String source, String target) {
        int distance = 0;
        for (int i = 0; i < source.length(); ++i) {
            if (source.charAt(i) != target.charAt(i)) {
                ++distance;
            }
        }
        return distance;
    }
}
